package com.lollipop.programming.thread.productconsume;

import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.*;

/**
 * @Author Lollipop
 * @Date 2025/4/7 15:36
 * @Description 使用多线程实现生产者-消费者模型-BlockingQueue
 */
@Slf4j
public class ProducerConsumerV2 {
    private static final int MAX_CAPACITY = 5;
    // 总生产数量
    private static final int TOTAL_ITEMS = 20;
    private final BlockingQueue<Integer> queue = new LinkedBlockingQueue<>(MAX_CAPACITY);
    private volatile boolean isRunning = true;

    public static void main(String[] args) throws InterruptedException {
        ProducerConsumerV2 pc = new ProducerConsumerV2();

        Thread producer = new Thread(() -> {
            try {
                pc.produce();
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }, "Producer");

        Thread consumer = new Thread(() -> {
            try {
                pc.consume();
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }, "Consumer");

        producer.start();
        consumer.start();

        // 等待生产消费完成
        producer.join();
        // 通知消费者停止
        pc.shutdown();
        consumer.join();

        log.info("==== 程序正常结束 ====");
    }

    public void produce() throws InterruptedException {
        for (int i = 0; i < TOTAL_ITEMS && isRunning; i++) {
            queue.put(i);
            log.info("{} 生产: {} (库存: {})", Thread.currentThread().getName(), i, queue.size());
            // 生产间隔
            Thread.sleep(300);
        }
        log.info("{} --> 生产者完成", Thread.currentThread().getName());
    }

    public void consume() throws InterruptedException {
        while (isRunning || !queue.isEmpty()) {
            // 带超时的获取
            Integer value = queue.poll(500, TimeUnit.MILLISECONDS);
            if (value != null) {
                log.info("{} 消费: {} (剩余: {})", Thread.currentThread().getName(), value, queue.size());
                // 消费间隔
                Thread.sleep(1000);
            }
        }
        log.info("{} --> 消费者完成", Thread.currentThread().getName());
    }

    public void shutdown() {
        isRunning = false;
    }
}
